package com.sunye.upload.plugin.impl;

import com.aliyun.oss.*;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.ObjectMetadata;
import com.sunye.upload.plugin.FileManagerPlugin;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

/**
 * 阿里oss 文件操作
 *
 * @author Chopper
 */

@Component
@Slf4j
public class AliFileManagerPluginImpl implements FileManagerPlugin {
    private final String bucketName  = "lilishop-2022";
    private final String endpoint  = "oss-cn-beijing.aliyuncs.com";
    private final String accessKeyId   = "LTAI5t9waW23zQEy9CmLK9Et";
    private final String accessKeySecret  = "MKxAmPwO8SOwntyszMJ4HHl6RG8a4Q";


    /**
     * 获取oss client
     *
     * @return
     */
    private OSS getOssClient() {
        return new OSSClientBuilder().build(
                endpoint,
                accessKeyId,
                accessKeySecret);
    }

    /**
     * 获取配置前缀
     *
     * @return
     */
    private String getUrlPrefix() {
        return "https://" + bucketName + "." + endpoint + "/";
    }



    @Override
    public String pathUpload(String filePath, String key) {
        OSS ossClient = getOssClient();
        try {
            ossClient.putObject(bucketName, key, new File(filePath));
        } catch (OSSException oe) {
            log.error("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            log.error("Error Message: " + oe.getErrorMessage());
            log.error("Error Code:       " + oe.getErrorCode());
            log.error("Request ID:      " + oe.getRequestId());
            log.error("Host ID:           " + oe.getHostId());
            throw new ServiceException();
        } catch (ClientException ce) {
            log.error("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            log.error("Error Message: " + ce.getMessage());
            throw new ServiceException();
        } finally {
            /*
             * Do not forget to shut down the client finally to release all allocated resources.
             */
            ossClient.shutdown();
        }
        ossClient.shutdown();
        return getUrlPrefix() + key;
    }

    @Override
    public String inputStreamUpload(MultipartFile file,InputStream inputStream) {
        OSS ossClient = getOssClient();
        String fileKey = String.format("%s.%s", UUID.randomUUID().toString(), FilenameUtils.getExtension(file.getOriginalFilename()));
//        String fileName = file.getOriginalFilename();
//        String extName = fileName.substring(fileName.lastIndexOf("."));
//        String fileKey = UUID.randomUUID().toString().replace("-", "") + extName;
        try {
            ObjectMetadata meta = new ObjectMetadata();
            meta.setContentType("image/jpg");
//            meta.setContentType(getContentType(FilenameUtils.getExtension("." + file.getOriginalFilename())));
            ossClient.putObject(bucketName, fileKey, inputStream, meta);
        } catch (OSSException oe) {
            log.error("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            log.error("Error Message: " + oe.getErrorMessage());
            log.error("Error Code:       " + oe.getErrorCode());
            log.error("Request ID:      " + oe.getRequestId());
            log.error("Host ID:           " + oe.getHostId());
            throw new ServiceException();
        } catch (ClientException ce) {
            log.error("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            log.error("Error Message: " + ce.getMessage());
            throw new ServiceException();
        } finally {
            /*
             * Do not forget to shut down the client finally to release all allocated resources.
             */
            ossClient.shutdown();
        }
        ossClient.shutdown();
        return getUrlPrefix() + fileKey;
    }

    @Override
    public void deleteFile(List<String> key) {
        OSS ossClient = getOssClient();

        try {
            ossClient.deleteObjects(
                    new DeleteObjectsRequest(bucketName).withKeys(key));
        } catch (OSSException oe) {
            log.error("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            log.error("Error Message: " + oe.getErrorMessage());
            log.error("Error Code:       " + oe.getErrorCode());
            log.error("Request ID:      " + oe.getRequestId());
            log.error("Host ID:           " + oe.getHostId());
            throw new ServiceException();
        } catch (ClientException ce) {
            log.error("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            log.error("Error Message: " + ce.getMessage());
            throw new ServiceException();
        } finally {
            /*
             * Do not forget to shut down the client finally to release all allocated resources.
             */
            ossClient.shutdown();
        }
    }



    /**
     * 通过文件名判断并获取OSS服务文件上传时文件的contentType
     *
     * @param filenameExtension 文件名
     * @return 文件的contentType
     */
    public static final String getContentType(String filenameExtension) {

        if (filenameExtension.equalsIgnoreCase(".bmp")) {
            return "application/x-bmp";
        }
        if (filenameExtension.equalsIgnoreCase(".gif")) {
            return "image/gif";
        }
        if (filenameExtension.equalsIgnoreCase(".jpeg") ||
                filenameExtension.equalsIgnoreCase(".jpg") ||
                filenameExtension.equalsIgnoreCase(".png")) {
            return "image/jpg";
        }
        if (filenameExtension.equalsIgnoreCase(".html")) {
            return "text/html";
        }
        if (filenameExtension.equalsIgnoreCase(".txt")) {
            return "text/plain";
        }
        if (filenameExtension.equalsIgnoreCase(".vsd")) {
            return "application/vnd.visio";
        }
        if (filenameExtension.equalsIgnoreCase(".pptx") ||
                filenameExtension.equalsIgnoreCase(".ppt")) {
            return "application/vnd.ms-powerpoint";
        }
        if (filenameExtension.equalsIgnoreCase(".docx") ||
                filenameExtension.equalsIgnoreCase(".doc")) {
            return "application/msword";
        }
        if (filenameExtension.equalsIgnoreCase(".xla") ||
                filenameExtension.equalsIgnoreCase(".xlc") ||
                filenameExtension.equalsIgnoreCase(".xlm") ||
                filenameExtension.equalsIgnoreCase(".xls") ||
                filenameExtension.equalsIgnoreCase(".xlt") ||
                filenameExtension.equalsIgnoreCase(".xlw")) {
            return "application/vnd.ms-excel";
        }
        if (filenameExtension.equalsIgnoreCase(".xlsx")) {
            return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        }
        if (filenameExtension.equalsIgnoreCase(".xml")) {
            return "text/xml";
        }
        if (filenameExtension.equalsIgnoreCase(".pdf")) {
            return "application/pdf";
        }
        if (filenameExtension.equalsIgnoreCase(".zip")) {
            return "application/zip";
        }
        if (filenameExtension.equalsIgnoreCase(".tar")) {
            return "application/x-tar";
        }
        if (filenameExtension.equalsIgnoreCase(".avi")) {
            return "video/avi";
        }
        if (filenameExtension.equalsIgnoreCase(".mp4")) {
            return "video/mpeg4";
        }
        if (filenameExtension.equalsIgnoreCase(".mp3")) {
            return "audio/mp3";
        }
        if (filenameExtension.equalsIgnoreCase(".mp2")) {
            return "audio/mp2";
        }
        // 默认下载
//        return "application/octet-stream";
        return "image/jpg";
    }
}
